package com.corticon.dialogs.dao.hibernate;

import static org.hibernate.criterion.Restrictions.*;

import java.util.List;

import org.apache.commons.lang.StringUtils;

import org.hibernate.Criteria;
import org.hibernate.criterion.CriteriaSpecification;
import org.hibernate.criterion.MatchMode;

import org.springframework.stereotype.Repository;

import com.corticon.dialogs.dao.QuestionnaireDAO;
import com.corticon.dialogs.model.Questionnaire;
import com.corticon.dialogs.model.UserGroup;
import com.corticon.dialogs.util.Pager;

@Repository("questionnaireDAO")
public class QuestionnaireHibernateDAO extends GenericHibernateDAO<Questionnaire, Long> implements
    QuestionnaireDAO {

    public int GetMaxNumber() {
        List Lmax = this.findBySQLQuery("select max(a.id) from q_dialog a ");
        if (Lmax != null && Lmax.size() >= 1) {
            if (Lmax.get(0) == null) {
                return 0;
            }
            String CutPix = Lmax.get(0).toString().replace("D", "");
            CutPix = CutPix.replace("-", "");
            return Integer.valueOf(CutPix);
        }
        return 0;
    }

    @Override
    public String findMaxRefId() {
        return (String) getSession().getNamedQuery("Questionnaire.findMaxRefId").uniqueResult();
    }

    @Override
    public long findMaxVersionByRefId(String refId) {
        return (Long) getSession().getNamedQuery("Questionnaire.findMaxVersionByRefId").setString(
            "refId", refId).uniqueResult();
    }

    @Override
    public long getCountByGroup(UserGroup group) {
        return getCount(getCriteriaByGroup(group));
    }

    private Criteria getCriteriaByGroup(UserGroup group) {
        Criteria criteria = getBaseCriteria();
        criteria.createCriteria("modifiedBy").add(eq("userGroup", group));
        return criteria;
    }

    @Override
    public List<Questionnaire> getPageOfDataByGroup(UserGroup group, Pager pager) {
        return getPageOfData(getCriteriaByGroup(group), pager);
    }

    @Override
    public List<Questionnaire> search(String keywords, String function, String region,
        String productType, String locale, String status, String username, String groupName,
        Pager pager) {

        Criteria countCriteria =
            buildSearchCriteria(keywords, function, region, productType, locale, status, username,
            groupName);

        pager.setNumOfRecords(getCount(countCriteria));

        Criteria searchCriteria = buildSearchCriteria(keywords, function, region, productType,
            locale, status, username, groupName);

        return getPageOfData(searchCriteria, pager);
    }

    private Criteria buildSearchCriteria(String keywords, String function, String region,
        String productType, String locale, String status, String username, String groupName) {

        Criteria criteria = getBaseCriteria();

        keywords = keywords.trim();

        if (StringUtils.isNotEmpty(keywords)) {
            criteria.createAlias("sibling", "s", CriteriaSpecification.LEFT_JOIN).add(disjunction().
                add(ilike("refId", keywords, MatchMode.ANYWHERE)).add(ilike("displayTitle", keywords,
                MatchMode.ANYWHERE)).add(ilike("description", keywords, MatchMode.ANYWHERE)).add(ilike(
                "name", keywords, MatchMode.ANYWHERE)).add(ilike(
                        "vocabularyname", keywords, MatchMode.ANYWHERE)).add(ilike("s.refId", keywords,
                MatchMode.ANYWHERE)));
        }

        if (StringUtils.isNotEmpty(function)) {
            criteria.createCriteria("function").add(eq("code", function));
        }

        if (StringUtils.isNotEmpty(region)) {
            criteria.createCriteria("region").add(eq("code", region));
        }

        if (StringUtils.isNotEmpty(productType)) {
            criteria.createCriteria("productType").add(eq("code", productType));
        }

        if (StringUtils.isNotEmpty(locale)) {
            criteria.createCriteria("locale").add(eq("code", locale));
        }

        if (StringUtils.isNotEmpty(status)) {
            criteria.createCriteria("publicationStatus").add(eq("code", status));
        }

        if (StringUtils.isNotEmpty(username)) {
            criteria.createCriteria("modifiedBy").add(eq("username", username));
        } else if (StringUtils.isNotEmpty(groupName)) {
            criteria.createCriteria("modifiedBy").createCriteria("userGroup").add(eq("name",
                groupName));
        }

        return criteria;
    }
}